#include <iostream>
#include <string>
#include <unordered_map>

// 1、抽象原型类
class Shape {
public:
    virtual ~Shape() {}
    virtual Shape* clone() = 0;
    virtual int getid() = 0;
    virtual std::string getType() = 0;
protected:
    std::string Type_;
private:
    int id_;

};

// 2、三个形状具体原型
class Circle : public Shape {
public:
    Circle(std::string Type,int id):Type_(Type),id_(id) {}
    Circle(const Circle& lhs) {
        Type_ = lhs.Type_;
        id_ = lhs.id_;
    }
    ~Circle() {}
    virtual Shape* clone() {
        return new Circle(*this);
    }
    virtual int getid() {
        return id_;
    }
    virtual std::string getType() {
        return Type_;
    }
protected:
    std::string Type_;
private:
    int id_;
};

class Rectangle : public Shape {
public:
    Rectangle(std::string Type,int id):Type_(Type),id_(id) {}
    Rectangle(const Rectangle& lhs) {
        Type_ = lhs.Type_;
        id_ = lhs.id_;
    }
    ~Rectangle() {}
    virtual Shape* clone() {
        return new Rectangle(*this);
    }
    virtual int getid() {
        return id_;
    }
    virtual std::string getType() {
        return Type_;
    }
protected:
    std::string Type_;
private:
    int id_;
};

class Square : public Shape {
public:
    Square(std::string Type,int id):Type_(Type),id_(id) {}
    Square(const Square& lhs) {
        Type_ = lhs.Type_;
        id_ = lhs.id_;
    }
    ~Square() {}
    virtual Shape* clone() {
        return new Square(*this);
    }
    virtual int getid() {
        return id_;
    }
    virtual std::string getType() {
        return Type_;
    }
protected:
    std::string Type_;
private:
    int id_;
};

// 3、存储对象种类的数据库
class ShapeType {
public:
    ~ShapeType() {
        for(auto& x : ShapeMap_) {
            delete x.second;
            x.second = nullptr;
        }
    }
    // 构造原始对象
    ShapeType() {
        Circle* circle = new Circle("圆形",1);
        Rectangle* rectangle = new Rectangle("矩形",2);
        Square* square = new Square("正方形",3);
        ShapeMap_.emplace(circle->getType(),circle);
        ShapeMap_.emplace(rectangle->getType(),rectangle);
        ShapeMap_.emplace(square->getType(),square);
    }
    // 根据你所需要的种类来获取克隆对象
    Shape* getShape(std::string Type) {
        return ShapeMap_[Type]->clone();
    }
private:
    std::unordered_map<std::string,Shape*> ShapeMap_;
};

int main() {
    std::cout << "hello prototype!!!" << std::endl;
    //  1、创建对象种类库
    ShapeType obj;
    // 2、从对象库获得对象的克隆体
    Shape* m_circle = obj.getShape("圆形");
    Shape* m_square = obj.getShape("正方形");
    Shape* m_rectangle = obj.getShape("矩形");

    std::cout << m_circle->getid() << " : " << m_circle->getType() << std::endl;
    std::cout << m_square->getid() << " : " << m_square->getType() << std::endl;
    std::cout << m_rectangle->getid() << " : " << m_rectangle->getType() << std::endl;

    delete m_circle;
    delete m_square;
    delete m_rectangle;
    m_circle = nullptr;
    m_rectangle = nullptr;
    m_square = nullptr;
    return 0;
}